/*
 * Utils.hpp

 *
 *  Created on: 2021楠�锟�7��锟�20��锟�
 *      Author: root
 */
#include <iostream>
#include<vector>
#include <map>
#include "Series.cpp"
#include <hiredis/hiredis.h>
#include <sw/redis++/redis++.h>
using namespace std;
class utils {
public:
	static void SplitString(const std::string& s, std::vector<std::string>& v, const std::string& c) {
		std::string::size_type pos1, pos2;
		pos2 = s.find(c);
		pos1 = 0;
		while (std::string::npos != pos2) {
			v.push_back(s.substr(pos1, pos2 - pos1));

			pos1 = pos2 + c.size();
			pos2 = s.find(c, pos1);
		}
		if (pos1 != s.length())
			v.push_back(s.substr(pos1));
	}

	static bool cmp_key(const pair<double, int> left, const pair<double, int> right) {
		return left.first < right.first;
	}
    static void splitTime(const std::string& timeStr, int& hour, int& minute, int& second) {
        std::istringstream iss(timeStr);
        char delim;
        if (!(iss >> hour >> delim >> minute >> delim >> second) || delim != ':') {
            // 如果解析失败，你可以设置一些默认值或抛出一个异常
            hour = minute = second = 0; // 或者抛出一个异常
        }
    }


};

class IndicatorUtil {
public:

	static double ma(Series<double>* p, int n) {
		double sum = 0.0;
		for (int i = 0; i < n; ++i) {
			sum += p->get(i);
		}
		return sum / (double) n;
	}

	static double ma(Series<double>* x, int n, double lastMA) {
		double sum = lastMA * (double) n - x->get(n) + x->get(0);
		return sum / (double) n;
	}
};

class Redis {
private:

	redisContext* _connect = nullptr;
	redisReply* _reply = nullptr;
public:

	Redis() = default;

	~Redis() {
		if (_connect != nullptr) {
			delete _connect;

			this->_connect = nullptr;
		}
		if (_reply != nullptr) {
//			delete _reply;
//			cout<<"_reply"<<endl;
			this->_reply = nullptr;
		}
	}




	bool connect(const std::string& host, int port) {
		this->_connect = redisConnect(host.c_str(), port);
		if (this->_connect != nullptr && this->_connect->err) {
			printf("connect error: %s\n", this->_connect->errstr);
			return false;
		}
		string auth = "Ysy1404325082";
		redisCommand(this->_connect, "AUTH %s", auth.c_str());
		return true;
	}

	bool exists(const std::string& key)
	{
		this->_reply = (redisReply*) redisCommand(this->_connect, "EXISTS %s", key.c_str());

		return this->_reply->integer;

	}
	bool hexist(const std::string& key,const std::string& field)
	{
		this->_reply = (redisReply*) redisCommand(this->_connect, "HEXISTS %s %s", key.c_str(),field.c_str());

		return this->_reply->integer;
	}



	std::string get(const std::string& key) {
		this->_reply = (redisReply*) redisCommand(this->_connect, "GET %s", key.c_str());
		std::string str = this->_reply->str;
		freeReplyObject(this->_reply);
		return str;
	}

	void lpush(const std::string& key,const std::string& value)
	{

		redisCommand(this->_connect, "LPUSH %s %s", key.c_str(), value.c_str());
	}

	std::string hget(const std::string& key,const  std::string& field) {

		this->_reply = (redisReply*) redisCommand(this->_connect, "HGET %s %s", key.c_str(), field.c_str());
		if (this->_reply->str != nullptr) {
			std::string str = this->_reply->str;
			freeReplyObject(this->_reply);
			return str;
		} else {

			freeReplyObject(this->_reply);
			return "";
		}
	}
	std::vector<string> lrange(const std::string& key,const  string& begin,const string& size) {
		vector<string> v;
		cout<<key<<endl;
		this->_reply = (redisReply*) redisCommand(this->_connect, "LRANGE %s %s %s", key.c_str(), begin.c_str(), size.c_str());
		if (_reply->type == REDIS_REPLY_ARRAY) {
			unsigned long len=_reply->elements;
			for (int i = 0; i < len;++i  ) {
				v.emplace_back(_reply->element[i]->str);

			}
		}
		return v;
	}

	std::map<string, string> hgetall(const std::string& key) {
		std::map<string, string> maps;
		this->_reply = (redisReply*) redisCommand(this->_connect, "HGETALL %s", key.c_str());
		if(_reply!=nullptr)
		{
		if (_reply->type == REDIS_REPLY_ARRAY) {
			unsigned long size = _reply->elements;
			for (int i = 0; i < size; i = i + 2) {
				maps.insert(pair<string, string>(_reply->element[i]->str, _reply->element[i + 1]->str));

			}
		}

		freeReplyObject(this->_reply);
		}
		return maps;
	}
	void set(const std::string& key, const std::string& value) {
		redisCommand(this->_connect, "SET %s %s", key.c_str(), value.c_str());
	}
	void hset(const std::string& key,const  std::string& field,const  std::string& value) {
		redisCommand(this->_connect, "HSET %s %s %s", key.c_str(), field.c_str(), value.c_str());
	}

};
class RedisImp {
private:
    sw::redis::ConnectionOptions connection_options;
    sw::redis::ConnectionPoolOptions pool_options;

public:
    RedisImp(const string& host) {
        connection_options.host = host;  // Required.
        connection_options.port = 6379; // Optional. The default port is 6379.
        connection_options.password = "Ysy1404325082";   // Optional. No password by default.
        connection_options.db = 0;  // Optional. Use the 0th database by default.
        connection_options.socket_timeout = std::chrono::milliseconds(500);
        pool_options.size = 4;  // Pool size, i.e. max number of connections.
        pool_options.wait_timeout = std::chrono::milliseconds(1000);
        pool_options.connection_lifetime = std::chrono::minutes(10);
    }

    sw::redis::Redis getRedis()
    {
        //auto it=sw::redis::ConnectionPool(pool_options,connection_options);

        sw::redis::Redis r=sw::redis::Redis(connection_options,pool_options);
        return r;
    }

};
